"""
STS协议核心模块
实现完整的STS通信协议
"""

import time
from typing import Optional, Dict, Any, Tuple
from .crypto import STSCrypto
from .token import STSToken
from .utils import STSUtils


class STSProtocol:
    """STS协议类"""
    
    def __init__(self, crypto: Optional[STSCrypto] = None):
        """
        初始化STS协议
        
        Args:
            crypto: 加密模块实例
        """
        self.crypto = crypto or STSCrypto()
        self.token_handler = STSToken(self.crypto)
        self.utils = STSUtils()
        
        # 协议状态
        self.session_active = False
        self.current_meter_id = None
        self.transfer_counter = 0
    
    def start_session(self, meter_id: str) -> Dict[str, Any]:
        """
        开始STS会话
        
        Args:
            meter_id: 表计ID
            
        Returns:
            会话状态信息
        """
        if not self.utils.validate_meter_id(meter_id):
            return {
                'success': False,
                'error': 'Invalid meter ID format'
            }
        
        self.current_meter_id = meter_id
        self.session_active = True
        self.transfer_counter = self.utils.generate_transfer_counter()
        
        return {
            'success': True,
            'meter_id': meter_id,
            'transfer_counter': self.transfer_counter,
            'session_id': f"STS_{int(time.time())}"
        }
    
    def end_session(self) -> Dict[str, Any]:
        """
        结束STS会话
        
        Returns:
            会话结束状态
        """
        if not self.session_active:
            return {
                'success': False,
                'error': 'No active session'
            }
        
        session_info = {
            'success': True,
            'meter_id': self.current_meter_id,
            'transfer_counter': self.transfer_counter
        }
        
        self.session_active = False
        self.current_meter_id = None
        self.transfer_counter = 0
        
        return session_info
    
    def generate_recharge_token(self, amount: int) -> Dict[str, Any]:
        """
        生成充值令牌
        
        Args:
            amount: 充值金额（以分为单位）
            
        Returns:
            令牌生成结果
        """
        if not self.session_active:
            return {
                'success': False,
                'error': 'No active session'
            }
        
        if not self.utils.validate_amount(amount):
            return {
                'success': False,
                'error': 'Invalid amount'
            }
        
        try:
            # 生成令牌
            token = self.token_handler.generate_token(
                self.current_meter_id, 
                amount, 
                self.transfer_counter
            )
            
            # 增加传输计数器
            self.transfer_counter += 1
            
            return {
                'success': True,
                'token': token,
                'meter_id': self.current_meter_id,
                'amount': amount,
                'amount_formatted': self.utils.format_amount(amount),
                'transfer_counter': self.transfer_counter - 1
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': f'Token generation failed: {str(e)}'
            }
    
    def verify_recharge_token(self, token: str) -> Dict[str, Any]:
        """
        验证充值令牌
        
        Args:
            token: 令牌字符串
            
        Returns:
            验证结果
        """
        if not self.session_active:
            return {
                'success': False,
                'error': 'No active session'
            }
        
        if not self.token_handler.validate_token_format(token):
            return {
                'success': False,
                'error': 'Invalid token format'
            }
        
        # 验证令牌
        is_valid, token_info = self.token_handler.verify_token(token, self.current_meter_id)
        
        if not is_valid:
            return {
                'success': False,
                'error': 'Token verification failed'
            }
        
        return {
            'success': True,
            'token_info': token_info,
            'amount_formatted': self.utils.format_amount(token_info['amount']),
            'meter_id': token_info['meter_id']
        }
    
    def read_meter_data(self) -> Dict[str, Any]:
        """
        读取表计数据（模拟）
        
        Returns:
            表计数据
        """
        if not self.session_active:
            return {
                'success': False,
                'error': 'No active session'
            }
        
        # 模拟表计数据
        meter_data = {
            'meter_id': self.current_meter_id,
            'current_balance': 5000,  # 50元
            'total_consumption': 12345,  # 立方米
            'last_recharge': int(time.time()) - 86400,  # 1天前
            'status': 'NORMAL',
            'alarm_status': 'NONE'
        }
        
        return {
            'success': True,
            'data': meter_data,
            'timestamp': self.utils.format_timestamp()
        }
    
    def send_command(self, command: str, parameters: Optional[Dict] = None) -> Dict[str, Any]:
        """
        发送STS命令
        
        Args:
            command: 命令类型
            parameters: 命令参数
            
        Returns:
            命令执行结果
        """
        if not self.session_active:
            return {
                'success': False,
                'error': 'No active session'
            }
        
        command = command.upper()
        
        if command == 'READ_METER':
            return self.read_meter_data()
        
        elif command == 'GENERATE_TOKEN':
            if not parameters or 'amount' not in parameters:
                return {
                    'success': False,
                    'error': 'Amount parameter required'
                }
            return self.generate_recharge_token(parameters['amount'])
        
        elif command == 'VERIFY_TOKEN':
            if not parameters or 'token' not in parameters:
                return {
                    'success': False,
                    'error': 'Token parameter required'
                }
            return self.verify_recharge_token(parameters['token'])
        
        elif command == 'GET_STATUS':
            return {
                'success': True,
                'session_active': self.session_active,
                'meter_id': self.current_meter_id,
                'transfer_counter': self.transfer_counter
            }
        
        else:
            return {
                'success': False,
                'error': f'Unknown command: {command}'
            }
    
    def create_communication_packet(self, command: str, data: bytes) -> bytes:
        """
        创建通信数据包
        
        Args:
            command: 命令类型
            data: 数据内容
            
        Returns:
            完整的数据包
        """
        # STS数据包格式: [STX][LENGTH][COMMAND][DATA][CRC][ETX]
        STX = 0x02
        ETX = 0x03
        
        command_bytes = command.encode('ascii')
        length = len(command_bytes) + len(data)
        
        packet = bytes([STX]) + bytes([length]) + command_bytes + data
        
        # 计算CRC
        crc = self.crypto.calculate_crc16(packet[1:])  # 不包括STX
        packet += crc.to_bytes(2, 'little')
        packet += bytes([ETX])
        
        return packet
    
    def parse_communication_packet(self, packet: bytes) -> Dict[str, Any]:
        """
        解析通信数据包
        
        Args:
            packet: 数据包字节
            
        Returns:
            解析结果
        """
        try:
            if len(packet) < 6:
                return {
                    'success': False,
                    'error': 'Packet too short'
                }
            
            if packet[0] != 0x02 or packet[-1] != 0x03:
                return {
                    'success': False,
                    'error': 'Invalid packet format'
                }
            
            length = packet[1]
            command_end = 2 + length
            
            if len(packet) < command_end + 3:  # +3 for CRC and ETX
                return {
                    'success': False,
                    'error': 'Packet length mismatch'
                }
            
            command = packet[2:command_end].decode('ascii')
            data = packet[command_end:-3]
            crc = int.from_bytes(packet[-3:-1], 'little')
            
            # 验证CRC
            calculated_crc = self.crypto.calculate_crc16(packet[1:-3])
            if calculated_crc != crc:
                return {
                    'success': False,
                    'error': 'CRC verification failed'
                }
            
            return {
                'success': True,
                'command': command,
                'data': data,
                'crc': crc
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': f'Packet parsing failed: {str(e)}'
            }
    
    def get_protocol_info(self) -> Dict[str, Any]:
        """
        获取协议信息
        
        Returns:
            协议信息
        """
        return {
            'protocol_name': 'STS (Standard Transfer Specification)',
            'version': '1.0.0',
            'encryption': 'DES',
            'crc_type': 'CRC16',
            'token_format': 'Hexadecimal with grouping',
            'supported_commands': [
                'READ_METER',
                'GENERATE_TOKEN',
                'VERIFY_TOKEN',
                'GET_STATUS'
            ]
        }
